package com.code.family.utils;

import com.code.family.entity.annotation.OperationLog;
import com.code.family.entity.pojo.OperationLogs;
import com.code.family.service.OperationLogsService;
import jakarta.annotation.Resource;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * 切面类
 * 拦截带有`@OperationLog`注解的方法记录日志。
 *
 * @author 上玄
 */
@Aspect
@Component
public class OperationLogAspect {

    @Resource
    private OperationLogsService operationLogService;

    // 定义切入点
    @Pointcut("@annotation(com.code.family.entity.annotation.OperationLog)")
    public void operationLogPointCut() {}

    // 在方法执行后记录日志
    @AfterReturning(pointcut = "operationLogPointCut()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        saveLog(joinPoint, null);
    }

    // 在方法抛出异常后记录日志
    @AfterThrowing(pointcut = "operationLogPointCut()", throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint, Throwable exception) {
        saveLog(joinPoint, exception);
    }

    private void saveLog(JoinPoint joinPoint, Throwable exception) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        OperationLog operationLog = signature.getMethod().getAnnotation(OperationLog.class);
        String description = operationLog.description();

        // 获取请求信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = null;
        if (attributes != null) {
            request = attributes.getRequest();
        }

        String url = null;
        if (request != null) {
            url = request.getRequestURL().toString();
        }
        String method = null;
        if (request != null) {
            method = request.getMethod();
        }
        // 获取ip地址
        String ip = IpUtils.getIpAddr(request);

        // 创建日志实体
        OperationLogs logEntity = new OperationLogs();
        logEntity.setDescription(description);
        logEntity.setUrl(url);
        logEntity.setMethod(method);
        logEntity.setIp(ip);
        logEntity.setException(exception != null ? exception.getMessage() : null);
        logEntity.setCreateTime(new Date());

        // 保存日志
        operationLogService.save(logEntity);
    }
}
